Distributed systems allow multiple clients in a network to access a pool of shared resources. For example, a distributed storage system allows a cluster of host computers to aggregate local disks (e.g., SSD, PCI-based flash storage, SATA, or SAS magnetic disks) located in or attached to each host computer to create a single and shared pool of storage. This pool of storage (sometimes referred to herein as a “datastore” or “store”) is accessible by all host computers in the cluster and may be presented as a single namespace of storage entities (such as a hierarchical file system namespace in the case of files, a flat namespace of unique identifiers in the case of objects, etc.). Storage clients in turn, such as virtual machines spawned on the host computers may use the datastore, for example, to store virtual disks that are accessed by the virtual machines during their operation. Because the shared local disks that make up the datastore may have different performance characteristics (e.g., capacity, input/output per second or IOPS capabilities, etc.), usage of such shared local disks to store virtual disks or portions thereof may be distributed among the virtual machines based on the needs of each given virtual machine.
This approach provides enterprises with cost-effective performance. For instance, distributed storage using pooled local disks is inexpensive, highly scalable, and relatively simple to manage. Because such distributed storage can use commodity disks in the cluster, enterprises do not need to invest in additional storage infrastructure. One issue that arises in utilizing a datastore backed by a shared pool of possible diverse commodity storage devices (each potentially having different storage specifications) is determining how to store data within (or across) such a shared pool on behalf of different clients that may desire different storage characteristics for their data storage and access. For example, if the datastore is used to provision “virtual disks” for clients such as virtual machines, some virtual machines may run applications that are mission-critical and thus require virtual disks that exhibit high availability (and redundancy) while other virtual machines may run time-sensitive applications which require high IOPS when accessing storage. The challenge is how to ultimately map these various storage requirements to the appropriate local storage devices in a manner that can satisfy the requirements.